home *** CD-ROM | disk | FTP | other *** search
/ Aminet 7 / Aminet 7 - August 1995.iso / Aminet / comm / tcp / amitcptelnetf.lha / amitcp_telnet+ftp / ftp / main.c < prev    next >
C/C++ Source or Header  |  1993-08-13  |  10KB  |  596 lines

  1. /*
  2.  * Copyright (c) 1985, 1989 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. char copyright[] =
  20. "@(#) Copyright (c) 1985, 1989 Regents of the University of California.\n\
  21.  All rights reserved.\n";
  22. #endif /* not lint */
  23.  
  24. #ifndef lint
  25. static char sccsid[] = "@(#)main.c    based on 5.13 (Berkeley) 3/14/89";
  26. #endif /* not lint */
  27.  
  28. /*
  29.  * FTP User Program -- Command Interface.
  30.  */
  31. #define FTPVARS
  32. #include "ftp_var.h"
  33. #include <sys/socket.h>
  34. #ifdef AMI_TCP
  35. #include <bsdsocket.h>
  36. #else
  37. #include <ss/socket.h>
  38. #endif
  39. #include <sys/ioctl.h>
  40. #include <sys/types.h>
  41.  
  42. #include <arpa/ftp.h>
  43.  
  44. #include <signal.h>
  45. #include <stdio.h>
  46. #include <errno.h>
  47. #include <ctype.h>
  48. #include <netdb.h>
  49. #ifndef AMI_TCP
  50. #include <pwd.h>
  51. #endif
  52. //#include <syslog.h>
  53.  
  54. #ifdef __SASC
  55. int Enable_Abort;
  56. #endif
  57.  
  58. #if defined(sun) && !defined(FD_SET)
  59. typedef int uid_t;
  60. #endif
  61.  
  62. const static char versino[] = "$VER: ftp 2.0 (13.8.93)";
  63.  
  64. sig_t    intr();
  65. sig_t    lostpeer();
  66. char    *getlogin();
  67. extern char *home;
  68.  
  69. struct Library *OpenLibrary();
  70. #ifdef AMI_TCP
  71. struct Library *SocketBase=0;
  72. #else
  73. struct Library *SockBase=0;
  74. #endif
  75.  
  76. FILE *log_file = 0;
  77.  
  78. shut_down()
  79. {
  80.     if (log_file) fclose(log_file);
  81.     log_file = 0;
  82. #ifdef AMI_TCP
  83.     if (SocketBase)
  84.         CloseLibrary(SocketBase);
  85.     SocketBase = 0;
  86. #else
  87.     if (SockBase)
  88.     {    cleanup_sockets();
  89.         CloseLibrary(SockBase);
  90.     }
  91.     SockBase = 0;
  92. #endif
  93. }
  94.  
  95. extern int Enable_Abort;
  96.  
  97. main(argc, argv)
  98.     char *argv[];
  99. {
  100.     register char *cp;
  101.     int top;
  102.     extern char *mygetenv();
  103.  
  104. #ifdef AMI_TCP
  105.     SocketBase = OpenLibrary("bsdsocket.library", 2L);
  106.     SetErrnoPtr(&errno, sizeof errno);
  107. #else
  108.     SockBase = OpenLibrary("inet:libs/socket.library",0L);
  109.     setup_sockets(5,&errno);
  110. #endif
  111.     atexit(shut_down);
  112.  
  113.     sp = getservbyname("ftp", "tcp");
  114.     if (sp == 0) {
  115.         fprintf(stderr, "ftp: ftp/tcp: unknown service\n");
  116.         exit(1);
  117.     }
  118.     doglob = 0;
  119.     interactive = 1;
  120.     hash = 0;
  121.     logname = 0;
  122.     autologin = 1;
  123. #ifdef FTP_LOG_USAGE
  124. #ifdef LOG_LOCAL3
  125.         openlog("ftp", LOG_PID, LOG_LOCAL3);
  126. #else
  127.         openlog("ftp", LOG_PID);
  128. #endif /* LOG_LOCAL2 */
  129. #endif /* FTP_LOG_USAGE */
  130.     argc--, argv++;
  131.     while (argc > 0 && **argv == '-') {
  132.         for (cp = *argv + 1; cp && *cp; cp++)
  133.             switch (*cp) {
  134.  
  135.             case 'd':
  136.                 options |= SO_DEBUG;
  137.                 debug++;
  138.                 break;
  139.             
  140.             case 'v':
  141.                 verbose++;
  142.                 break;
  143.  
  144.             case 't':
  145.                 trace++;
  146.                 break;
  147.  
  148.             case 'i':
  149.                 interactive = 0;
  150.                 break;
  151.  
  152.             case 'n':
  153.                 autologin = 0;
  154.                 break;
  155.  
  156.             case 'g':
  157.                 doglob = 0;
  158.                 break;
  159.             case 'L':
  160.                 logname = cp+1;
  161.                 cp = 0;
  162.                 break;
  163.             case 'H':
  164.                 hash = 1;
  165.                 break;
  166.             case 'D':
  167.                 dldir = cp+1;
  168.                 cp = 0;
  169.                 break;
  170.             case 'U':
  171.                 uldir = cp+1;
  172.                 cp = 0;
  173.                 break;
  174.             default:
  175.                 fprintf(stdout,
  176.                   "ftp: %c: unknown option\n", *cp);
  177.                 exit(1);
  178.             }
  179.         argc--, argv++;
  180.     }
  181.  
  182.     fromatty = isatty(fileno(stdin));
  183.     /*
  184.      * Set up defaults for FTP.
  185.      */
  186.     (void) strcpy(typename, "ascii"), type = TYPE_A;
  187.     (void) strcpy(formname, "non-print"), form = FORM_N;
  188.     (void) strcpy(modename, "stream"), mode = MODE_S;
  189.     (void) strcpy(structname, "file"), stru = STRU_F;
  190.     (void) strcpy(bytename, "8"), bytesize = 8;
  191.     if (fromatty)
  192.         verbose++;
  193.     cpend = 0;           /* no pending replies */
  194.     proxy = 0;    /* proxy not active */
  195.     crflag = 1;    /* strip c.r. on ascii gets */
  196.  
  197.     /*
  198.      * Set up the home directory in case we're globbing.
  199.      */
  200.  
  201.     if (uldir == 0 || dldir == 0)
  202.     {    char currentdir[MAXPATHLEN];
  203.         getcwd(currentdir,MAXPATHLEN);
  204.         if (uldir == 0) uldir = currentdir;
  205.         if (dldir == 0) dldir = currentdir;
  206.     }
  207.  
  208.     if (logname)
  209.         log_file = fopen(logname,"a");
  210.  
  211.     home = uldir;
  212.     if (argc > 0) {
  213.         if (setjmp(toplevel))
  214.             exit(0);
  215. #ifndef __SASC
  216.         (void) signal(SIGINT, intr);
  217.         (void) signal(SIGPIPE, lostpeer);
  218. #endif
  219.         setpeer(argc + 1, argv - 1);
  220.     }
  221.     else
  222.     {    printf("[FTP] ");
  223.         strcpy(line,"open");
  224.         makeargv();
  225.         if (setjmp(toplevel) == 0) {
  226. #ifndef __SASC
  227.             (void) signal(SIGINT, intr);
  228.             (void) signal(SIGPIPE, lostpeer);
  229. #endif
  230.             setpeer(margc,margv);
  231.         }
  232.     }
  233.     
  234.     top = setjmp(toplevel) == 0;
  235.     if (top) {
  236. #ifndef __SASC
  237.         (void) signal(SIGINT, intr);
  238.         (void) signal(SIGPIPE, lostpeer);
  239. #endif
  240.     }
  241.     for (;;) {
  242.         cmdscanner(top);
  243.         top = 1;
  244.     }
  245. }
  246.  
  247. sig_t
  248. intr()
  249. {
  250.  
  251.     longjmp(toplevel, 1);
  252. }
  253.  
  254. sig_t
  255. lostpeer()
  256. {
  257.     extern int cout;
  258.     extern int data;
  259.  
  260.     if (connected) {
  261.         if (cout >= 0) {
  262.             (void) shutdown(cout, 1+1);
  263.             (void) s_close(cout);
  264.             cout = -1;
  265.         }
  266.         if (data >= 0) {
  267.             (void) shutdown(data, 1+1);
  268.             (void) s_close(data);
  269.             data = -1;
  270.         }
  271.         connected = 0;
  272.     }
  273.     pswitch(1);
  274.     if (connected) {
  275.         if (cout >= 0) {
  276.             (void) shutdown(cout, 1+1);
  277.             (void) s_close(cout);
  278.             cout = -1;
  279.         }
  280.         connected = 0;
  281.     }
  282.     proxflag = 0;
  283.     pswitch(0);
  284. }
  285.  
  286. /*char *
  287. tail(filename)
  288.     char *filename;
  289. {
  290.     register char *s;
  291.     
  292.     while (*filename) {
  293.         s = rindex(filename, '/');
  294.         if (s == NULL)
  295.             break;
  296.         if (s[1])
  297.             return (s + 1);
  298.         *s = '\0';
  299.     }
  300.     return (filename);
  301. }
  302. */
  303. /*
  304.  * Command parser.
  305.  */
  306. cmdscanner(top)
  307.     int top;
  308. {
  309.     register struct cmd *c;
  310.     struct cmd *getcmd();
  311.     extern int help();
  312.  
  313.     if (!top)
  314.         (void) putchar('\n');
  315.     for (;;) {
  316.         if (fromatty) {
  317.             printf("ftp> ");
  318.             (void) fflush(stdout);
  319.         }
  320.         if (gets(line) == 0) {
  321.             if (feof(stdin) || ferror(stdin))
  322.                 quit();
  323.             break;
  324.         }
  325.         if (line[0] == 0)
  326.             break;
  327.         makeargv();
  328.         if (margc == 0) {
  329.             continue;
  330.         }
  331.         c = getcmd(margv[0]);
  332.         if (c == (struct cmd *)-1) {
  333.             printf("?Ambiguous command\n");
  334.             continue;
  335.         }
  336.         if (c == 0) {
  337.             printf("?Invalid command\n");
  338.             continue;
  339.         }
  340.         if (c->c_conn && !connected) {
  341.             printf ("Not connected.\n");
  342.             continue;
  343.         }
  344.         (*c->c_handler)(margc, margv);
  345.         if (bell && c->c_bell)
  346.             (void) putchar('\007');
  347.         if (c->c_handler != help)
  348.             break;
  349.     }
  350. #ifndef __SASC
  351.     (void) signal(SIGINT, intr);
  352.     (void) signal(SIGPIPE, lostpeer);
  353. #endif
  354. }
  355.  
  356. struct cmd *
  357. getcmd(name)
  358.     register char *name;
  359. {
  360.     extern struct cmd cmdtab[];
  361.     register char *p, *q;
  362.     register struct cmd *c, *found;
  363.     register int nmatches, longest;
  364.  
  365.     longest = 0;
  366.     nmatches = 0;
  367.     found = 0;
  368.     for (c = cmdtab; p = c->c_name; c++) {
  369.         for (q = name; *q == *p++; q++)
  370.             if (*q == 0)        /* exact match? */
  371.                 return (c);
  372.         if (!*q) {            /* the name was a prefix */
  373.             if (q - name > longest) {
  374.                 longest = q - name;
  375.                 nmatches = 1;
  376.                 found = c;
  377.             } else if (q - name == longest)
  378.                 nmatches++;
  379.         }
  380.     }
  381.     if (nmatches > 1)
  382.         return ((struct cmd *)-1);
  383.     return (found);
  384. }
  385.  
  386. /*
  387.  * Slice a string up into argc/argv.
  388.  */
  389.  
  390. int slrflag;
  391.  
  392. makeargv()
  393. {
  394.     char **argp;
  395.     char *slurpstring();
  396.  
  397.     margc = 0;
  398.     argp = margv;
  399.     stringbase = line;        /* scan from first of buffer */
  400.     argbase = argbuf;        /* store from first of buffer */
  401.     slrflag = 0;
  402.     while (*argp++ = slurpstring())
  403.         margc++;
  404. }
  405.  
  406. /*
  407.  * Parse string into argbuf;
  408.  * implemented with FSM to
  409.  * handle quoting and strings
  410.  */
  411. char *
  412. slurpstring()
  413. {
  414.     int got_one = 0;
  415.     register char *sb = stringbase;
  416.     register char *ap = argbase;
  417.     char *tmp = argbase;        /* will return this if token found */
  418.  
  419.     if (*sb == '!' || *sb == '$') {    /* recognize ! as a token for shell */
  420.         switch (slrflag) {    /* and $ as token for macro invoke */
  421.             case 0:
  422.                 slrflag++;
  423.                 stringbase++;
  424.                 return ((*sb == '!') ? "!" : "$");
  425.                 /* NOTREACHED */
  426.             case 1:
  427.                 slrflag++;
  428.                 altarg = stringbase;
  429.                 break;
  430.             default:
  431.                 break;
  432.         }
  433.     }
  434.  
  435. S0:
  436.     switch (*sb) {
  437.  
  438.     case '\0':
  439.         goto OUT;
  440.  
  441.     case ' ':
  442.     case '\t':
  443.         sb++; goto S0;
  444.  
  445.     default:
  446.         switch (slrflag) {
  447.             case 0:
  448.                 slrflag++;
  449.                 break;
  450.             case 1:
  451.                 slrflag++;
  452.                 altarg = sb;
  453.                 break;
  454.             default:
  455.                 break;
  456.         }
  457.         goto S1;
  458.     }
  459.  
  460. S1:
  461.     switch (*sb) {
  462.  
  463.     case ' ':
  464.     case '\t':
  465.     case '\0':
  466.         goto OUT;    /* end of token */
  467.  
  468.     case '\\':
  469.         sb++; goto S2;    /* slurp next character */
  470.  
  471.     case '"':
  472.         sb++; goto S3;    /* slurp quoted string */
  473.  
  474.     default:
  475.         *ap++ = *sb++;    /* add character to token */
  476.         got_one = 1;
  477.         goto S1;
  478.     }
  479.  
  480. S2:
  481.     switch (*sb) {
  482.  
  483.     case '\0':
  484.         goto OUT;
  485.  
  486.     default:
  487.         *ap++ = *sb++;
  488.         got_one = 1;
  489.         goto S1;
  490.     }
  491.  
  492. S3:
  493.     switch (*sb) {
  494.  
  495.     case '\0':
  496.         goto OUT;
  497.  
  498.     case '"':
  499.         sb++; goto S1;
  500.  
  501.     default:
  502.         *ap++ = *sb++;
  503.         got_one = 1;
  504.         goto S3;
  505.     }
  506.  
  507. OUT:
  508.     if (got_one)
  509.         *ap++ = '\0';
  510.     argbase = ap;            /* update storage pointer */
  511.     stringbase = sb;        /* update scan pointer */
  512.     if (got_one) {
  513.         return(tmp);
  514.     }
  515.     switch (slrflag) {
  516.         case 0:
  517.             slrflag++;
  518.             break;
  519.         case 1:
  520.             slrflag++;
  521.             altarg = (char *) 0;
  522.             break;
  523.         default:
  524.             break;
  525.     }
  526.     return((char *)0);
  527. }
  528.  
  529. #define HELPINDENT (sizeof ("directory"))
  530.  
  531. /*
  532.  * Help command.
  533.  * Call each command handler with argc == 0 and argv[0] == name.
  534.  */
  535. help(argc, argv)
  536.     int argc;
  537.     char *argv[];
  538. {
  539.     extern struct cmd cmdtab[];
  540.     register struct cmd *c;
  541.  
  542.     if (argc == 1) {
  543.         register int i, j, w, k;
  544.         int columns, width = 0, lines;
  545.         extern int NCMDS;
  546.  
  547.         printf("Commands may be abbreviated.  Commands are:\n\n");
  548.         for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
  549.             int len = strlen(c->c_name);
  550.  
  551.             if (len > width)
  552.                 width = len;
  553.         }
  554.         width = (width + 8) &~ 7;
  555.         columns = 80 / width;
  556.         if (columns == 0)
  557.             columns = 1;
  558.         lines = (NCMDS + columns - 1) / columns;
  559.         for (i = 0; i < lines; i++) {
  560.             for (j = 0; j < columns; j++) {
  561.                 c = cmdtab + j * lines + i;
  562.                 if (c->c_name && (!proxy || c->c_proxy)) {
  563.                     printf("%s", c->c_name);
  564.                 }
  565.                 else if (c->c_name) {
  566.                     for (k=0; k < strlen(c->c_name); k++) {
  567.                         (void) putchar(' ');
  568.                     }
  569.                 }
  570.                 if (c + lines >= &cmdtab[NCMDS]) {
  571.                     printf("\n");
  572.                     break;
  573.                 }
  574.                 w = strlen(c->c_name);
  575.                 while (w < width) {
  576.                     w = (w + 8) &~ 7;
  577.                     (void) putchar('\t');
  578.                 }
  579.             }
  580.         }
  581.         return;
  582.     }
  583.     while (--argc > 0) {
  584.         register char *arg;
  585.         arg = *++argv;
  586.         c = getcmd(arg);
  587.         if (c == (struct cmd *)-1)
  588.             printf("?Ambiguous help command %s\n", arg);
  589.         else if (c == (struct cmd *)0)
  590.             printf("?Invalid help command %s\n", arg);
  591.         else
  592.             printf("%-*s\t%s\n", HELPINDENT,
  593.                 c->c_name, c->c_help);
  594.     }
  595. }
  596.